{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5d904dee",
   "metadata": {},
   "source": [
    "# Example 6: Solving Partial Differential Equation (PDE)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d568912",
   "metadata": {},
   "source": [
    "We aim to solve a 2D poisson equation $\\nabla^2 f(x,y) = -2\\pi^2{\\rm sin}(\\pi x){\\rm sin}(\\pi y)$, with boundary condition $f(-1,y)=f(1,y)=f(x,-1)=f(x,1)=0$. The ground truth solution is $f(x,y)={\\rm sin}(\\pi x){\\rm sin}(\\pi y)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0e2bc449",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "pde loss: 2.76e+00 | bc loss: 1.17e-03 | l2: 3.09e-03 : 100%|███████| 50/50 [04:39<00:00,  5.58s/it]\n",
      "pde loss: 6.17e-01 | bc loss: 3.86e-04 | l2: 1.02e-03 : 100%|███████| 50/50 [04:41<00:00,  5.63s/it]\n",
      "pde loss: 3.59e-02 | bc loss: 2.90e-05 | l2: 5.40e-05 : 100%|███████| 50/50 [05:03<00:00,  6.06s/it]\n"
     ]
    }
   ],
   "source": [
    "from kan import KAN, LBFGS\n",
    "import torch\n",
    "import matplotlib.pyplot as plt\n",
    "from torch import autograd\n",
    "from tqdm import tqdm\n",
    "\n",
    "dim = 2\n",
    "np_i = 51 # number of interior points (along each dimension)\n",
    "np_b = 51 # number of boundary points (along each dimension)\n",
    "ranges = [-1, 1]\n",
    "\n",
    "\n",
    "def batch_jacobian(func, x, create_graph=False):\n",
    "    # x in shape (Batch, Length)\n",
    "    def _func_sum(x):\n",
    "        return func(x).sum(dim=0)\n",
    "    return autograd.functional.jacobian(_func_sum, x, create_graph=create_graph).permute(1,0,2)\n",
    "\n",
    "# define solution\n",
    "sol_fun = lambda x: torch.sin(torch.pi*x[:,[0]])*torch.sin(torch.pi*x[:,[1]])\n",
    "source_fun = lambda x: -2*torch.pi**2 * torch.sin(torch.pi*x[:,[0]])*torch.sin(torch.pi*x[:,[1]])\n",
    "\n",
    "# interior\n",
    "sampling_mode = 'mesh' # 'radnom' or 'mesh'\n",
    "\n",
    "x_mesh = torch.linspace(ranges[0],ranges[1],steps=np_i)\n",
    "y_mesh = torch.linspace(ranges[0],ranges[1],steps=np_i)\n",
    "X, Y = torch.meshgrid(x_mesh, y_mesh, indexing=\"ij\")\n",
    "if sampling_mode == 'mesh':\n",
    "    #mesh\n",
    "    x_i = torch.stack([X.reshape(-1,), Y.reshape(-1,)]).permute(1,0)\n",
    "else:\n",
    "    #random\n",
    "    x_i = torch.rand((np_i**2,2))*2-1\n",
    "\n",
    "# boundary, 4 sides\n",
    "helper = lambda X, Y: torch.stack([X.reshape(-1,), Y.reshape(-1,)]).permute(1,0)\n",
    "xb1 = helper(X[0], Y[0])\n",
    "xb2 = helper(X[-1], Y[0])\n",
    "xb3 = helper(X[:,0], Y[:,0])\n",
    "xb4 = helper(X[:,0], Y[:,-1])\n",
    "x_b = torch.cat([xb1, xb2, xb3, xb4], dim=0)\n",
    "\n",
    "alpha = 0.01\n",
    "log = 1\n",
    "\n",
    "\n",
    "grids = [5,10,20]\n",
    "steps = 50\n",
    "\n",
    "pde_losses = []\n",
    "bc_losses = []\n",
    "l2_losses = []\n",
    "\n",
    "for grid in grids:\n",
    "    if grid == grids[0]:\n",
    "        model = KAN(width=[2,2,1], grid=grid, k=3, seed=3)\n",
    "        model = model.speed()\n",
    "    else:\n",
    "        model.save_plot_data = True\n",
    "        model.get_act(x_i)\n",
    "        model = model.refine(grid)\n",
    "        model = model.speed()\n",
    "\n",
    "    def train():\n",
    "        optimizer = LBFGS(model.parameters(), lr=1, history_size=10, line_search_fn=\"strong_wolfe\", tolerance_grad=1e-32, tolerance_change=1e-32, tolerance_ys=1e-32)\n",
    "\n",
    "        pbar = tqdm(range(steps), desc='description', ncols=100)\n",
    "\n",
    "        for _ in pbar:\n",
    "            def closure():\n",
    "                global pde_loss, bc_loss\n",
    "                optimizer.zero_grad()\n",
    "                # interior loss\n",
    "                sol = sol_fun(x_i)\n",
    "                sol_D1_fun = lambda x: batch_jacobian(model, x, create_graph=True)[:,0,:]\n",
    "                sol_D1 = sol_D1_fun(x_i)\n",
    "                sol_D2 = batch_jacobian(sol_D1_fun, x_i, create_graph=True)[:,:,:]\n",
    "                lap = torch.sum(torch.diagonal(sol_D2, dim1=1, dim2=2), dim=1, keepdim=True)\n",
    "                source = source_fun(x_i)\n",
    "                pde_loss = torch.mean((lap - source)**2)\n",
    "\n",
    "                # boundary loss\n",
    "                bc_true = sol_fun(x_b)\n",
    "                bc_pred = model(x_b)\n",
    "                bc_loss = torch.mean((bc_pred-bc_true)**2)\n",
    "\n",
    "                loss = alpha * pde_loss + bc_loss\n",
    "                loss.backward()\n",
    "                return loss\n",
    "\n",
    "            if _ % 5 == 0 and _ < 20:\n",
    "                model.update_grid_from_samples(x_i)\n",
    "\n",
    "            optimizer.step(closure)\n",
    "            sol = sol_fun(x_i)\n",
    "            loss = alpha * pde_loss + bc_loss\n",
    "            l2 = torch.mean((model(x_i) - sol)**2)\n",
    "\n",
    "            if _ % log == 0:\n",
    "                pbar.set_description(\"pde loss: %.2e | bc loss: %.2e | l2: %.2e \" % (pde_loss.cpu().detach().numpy(), bc_loss.cpu().detach().numpy(), l2.detach().numpy()))\n",
    "\n",
    "            pde_losses.append(pde_loss.detach().numpy())\n",
    "            bc_losses.append(bc_loss.detach().numpy())\n",
    "            l2_losses.append(l2.detach().numpy())\n",
    "        \n",
    "    train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "dcbfa677",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7faaf9228070>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(pde_losses, marker='o')\n",
    "plt.plot(bc_losses, marker='o')\n",
    "plt.plot(l2_losses, marker='o')\n",
    "plt.yscale('log')\n",
    "plt.xlabel('steps')\n",
    "plt.legend(['PDE loss', 'BC loss', 'L2 squared'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bce40477",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
